﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.WindowsAPICodePack.Shell;
using Microsoft.WindowsAPICodePack.Dialogs;
using System.Windows.Forms;
using HalconDotNet;
using System.Windows;
using Microsoft.VisualBasic;
using System.ComponentModel;
using System.Reflection;
using Project1.Common;
using Project1.Element;
using Point = Project1.Element.Point;
using MessageBox = System.Windows.MessageBox;

namespace Project1
{
    public class Utils
    {
        public const string ImageFilesFilter = "图像文件 (*.bmp;*.jpg;*.tif;*.gif;*.png)|*.bmp;*.jpg;*.tif;*.gif;*.png";
        public const string ModuleFilesFilter = "模板文件 (*.shm)|*.shm";
        public const string CIRCLE = "CIRCLE";
        public const string POINT = "POINT";
        public const string LINE = "LINE";
        public const string PEAK_POINT = "PEAK_POINT";
        public static HTuple hv_ExpDefaultWinHandle;
        public static HTuple modelCentreRow, modelCentreColumn;
        public static HObject ho_Image;
        private const string default_module_savePath = "./";
        public HTuple windowHandle;
        public Utils()
        {
           
        }
        public static  string Get_path(string aim,bool isFolderPicker = false)
        {
            string fileName = "";
            
            if (isFolderPicker)
            {
                CommonOpenFileDialog dlg = new CommonOpenFileDialog();
                dlg.IsFolderPicker = true;
                CommonFileDialogResult result = dlg.ShowDialog();
                if (result != CommonFileDialogResult.Ok) return "";

                fileName = dlg.FileName;
              //  MessageBox.Show(fileName, "标题", MessageBoxButton.OK);
                
            }
            else
            {
                OpenFileDialog dlg = new OpenFileDialog();
                if (aim == ConstValue.MODULE)
                {
                    dlg.Filter = ModuleFilesFilter;
                }
                else if (aim == ConstValue.IMG)
                {
                    dlg.Filter = ImageFilesFilter;
                }
                if (dlg.ShowDialog() != DialogResult.OK) return "";
                fileName = dlg.FileName;
            }
           
            return fileName;
        }

        /// <summary>
        /// 显示测量数值
        /// </summary>
        /// <param name="hv_WindowHandle">窗口句柄</param>
        /// <param name="hv_String">要显示的文字</param>
        /// <param name="hv_CoordSystem">"image"或者"window"</param>
        /// <param name="hv_Row">显示的行</param>
        /// <param name="hv_Column">显示的列</param>
        /// <param name="hv_Color">字体颜色</param>
        /// <param name="hv_Box">"true" or "false" 是否显示背景框</param>
        public static void DispMessage(HTuple hv_WindowHandle, HTuple hv_String, HTuple hv_CoordSystem, HTuple hv_Row, HTuple hv_Column, HTuple hv_Color, HTuple hv_Box)
        {
            HTuple hv_GenParamName = null, hv_GenParamValue = null;
            HTuple hv_Color_COPY_INP_TMP = hv_Color.Clone();
            HTuple hv_Column_COPY_INP_TMP = hv_Column.Clone();
            HTuple hv_CoordSystem_COPY_INP_TMP = hv_CoordSystem.Clone();
            HTuple hv_Row_COPY_INP_TMP = hv_Row.Clone();
       
            if ((int)((new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(new HTuple()))).TupleOr(
                new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(new HTuple())))) != 0)
            {
                return;
            }
            if ((int)(new HTuple(hv_Row_COPY_INP_TMP.TupleEqual(-1))) != 0)
            {
                hv_Row_COPY_INP_TMP = 12;
            }
            if ((int)(new HTuple(hv_Column_COPY_INP_TMP.TupleEqual(-1))) != 0)
            {
                hv_Column_COPY_INP_TMP = 12;
            }
            //
            //Convert the parameter Box to generic parameters.
            hv_GenParamName = new HTuple();
            hv_GenParamValue = new HTuple();
            if ((int)(new HTuple((new HTuple(hv_Box.TupleLength())).TupleGreater(0))) != 0)
            {
                if ((int)(new HTuple(((hv_Box.TupleSelect(0))).TupleEqual("false"))) != 0)
                {
                    //Display no box
                    hv_GenParamName = hv_GenParamName.TupleConcat("box");
                    hv_GenParamValue = hv_GenParamValue.TupleConcat("false");
                }
                else if ((int)(new HTuple(((hv_Box.TupleSelect(0))).TupleNotEqual("true"))) != 0)
                {
                    //Set a color other than the default.
                    hv_GenParamName = hv_GenParamName.TupleConcat("box_color");
                    hv_GenParamValue = hv_GenParamValue.TupleConcat(hv_Box.TupleSelect(0));
                }
            }
            if ((int)(new HTuple((new HTuple(hv_Box.TupleLength())).TupleGreater(1))) != 0)
            {
                if ((int)(new HTuple(((hv_Box.TupleSelect(1))).TupleEqual("false"))) != 0)
                {
                    //Display no shadow.
                    hv_GenParamName = hv_GenParamName.TupleConcat("shadow");
                    hv_GenParamValue = hv_GenParamValue.TupleConcat("false");
                }
                else if ((int)(new HTuple(((hv_Box.TupleSelect(1))).TupleNotEqual("true"))) != 0)
                {
                    //Set a shadow color other than the default.
                    hv_GenParamName = hv_GenParamName.TupleConcat("shadow_color");
                    hv_GenParamValue = hv_GenParamValue.TupleConcat(hv_Box.TupleSelect(1));
                }
            }
            //Restore default CoordSystem behavior.
            if ((int)(new HTuple(hv_CoordSystem_COPY_INP_TMP.TupleNotEqual("window"))) != 0)
            {
                hv_CoordSystem_COPY_INP_TMP = "image";
            }
            //
            if ((int)(new HTuple(hv_Color_COPY_INP_TMP.TupleEqual(""))) != 0)
            {
                //disp_text does not accept an empty string for Color.
                hv_Color_COPY_INP_TMP = new HTuple();
            }
            //
            HOperatorSet.DispText(hv_ExpDefaultWinHandle, hv_String, hv_CoordSystem_COPY_INP_TMP,
                hv_Row_COPY_INP_TMP, hv_Column_COPY_INP_TMP, hv_Color_COPY_INP_TMP, hv_GenParamName,
                hv_GenParamValue);

            return;
        }

        public static   HObject Get_ROI_from_drawingObject(List<HTuple>drawing_objects)
        {
            HObject ROI = null;
            if (drawing_objects.Count == 0) return ROI;
            HObject tempROI = null;
            foreach (var drawingID in drawing_objects)
            {

                HOperatorSet.GetDrawingObjectIconic(out tempROI, drawingID);
                if (ROI == null)
                {
                    ROI = tempROI.Clone();
                }
                else
                {
                    HOperatorSet.Union2(ROI, tempROI, out ROI);
                }
                tempROI.Dispose();
            }
            return ROI;
        }
        public static   void Save_model(HTuple hv_ModelID,HObject ho_Image,HObject modelImage )
        {
            var fileName = Interaction.InputBox("请输入图样名称", "保存", "");
           // HObject modelImage = new HObject();
            if (fileName != "")
            {
                
                var filePath = default_module_savePath + fileName + ".shm";
                HOperatorSet.WriteShapeModel(hv_ModelID, filePath);
                HOperatorSet.WriteImage(modelImage, "bmp", 0, default_module_savePath + fileName);
                //HOperatorSet.DispObj(modelImage, hv_ExpDefaultWinHandle);

                modelImage.Dispose();
                MessageBox.Show("模型成功保存到" + filePath + "中", "caption", MessageBoxButton.OK);
                HOperatorSet.ClearShapeModel(hv_ModelID);
            }
            else
            {
                MessageBox.Show("没有输入图样名称，保存模型失败", "caption", MessageBoxButton.OK);
            }
            
        }

        public static   void Get_modelImage(HObject ho_Image,HTuple windowHandle, out HObject ho_BinImage, HTuple hv_ModelID)
        {
            // Stack for temporary objects 
            HObject[] OTemp = new HObject[20];

            // Local iconic variables 

            HObject ho_ModelContours, ho_TransContours = null;
            HObject ho_RegionXLD = null, ho_ImageReduced = null, ho_BiggestRegions = null;
            HObject ho_RegionSelected = null;

            // Local control variables 
            HTuple itemArea,maxArea, Row, Col;
            HTuple hv_Width = null, hv_Height = null, hv_Row = null;
            HTuple hv_Column = null, hv_Angle = null, hv_Score = null;
            HTuple hv_I = null, hv_Number = new HTuple(), hv_i = new HTuple();
            HTuple hv_Area = new HTuple();
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_BinImage);
            HOperatorSet.GenEmptyObj(out ho_ModelContours);
            HOperatorSet.GenEmptyObj(out ho_TransContours);
            HOperatorSet.GenEmptyObj(out ho_RegionXLD);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            HOperatorSet.GenEmptyObj(out ho_BiggestRegions);
            HOperatorSet.GenEmptyObj(out ho_RegionSelected);
            HOperatorSet.SetSystem("border_shape_models", "false");
            //read_image (Image, 'D:/Documents/Desktop/Sample.bmp')
            //read_shape_model ('D:/HALCONC#/Project1/bin/Debug/hellomodel.shm', ModelID)
            HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
            ho_ModelContours.Dispose();
            HOperatorSet.GetShapeModelContours(out ho_ModelContours, hv_ModelID, 1);
            HOperatorSet.FindShapeModel(ho_Image, hv_ModelID, (new HTuple(0)).TupleRad(),
                (new HTuple(360)).TupleRad(), 0.5, 1, 0.5, "least_squares", (new HTuple(6)).TupleConcat(
                1), 0.75, out hv_Row, out hv_Column, out hv_Angle, out hv_Score);
            //HOperatorSet.DispObj(ho_Image, hv_ExpDefaultWinHandle);
   
            for (hv_I = 0; (int)hv_I <= (int)((new HTuple(hv_Score.TupleLength())) - 1); hv_I = (int)hv_I + 1)
            {
                ho_TransContours.Dispose();
                Trans_contours(ho_ModelContours, windowHandle,out ho_TransContours, hv_Angle.TupleSelect(
                    hv_I), hv_Row.TupleSelect(hv_I), hv_Column.TupleSelect(hv_I));
                ho_RegionXLD.Dispose();
                HOperatorSet.GenRegionContourXld(ho_TransContours, out ho_RegionXLD, "filled");
                ho_ImageReduced.Dispose();
      
                ho_BiggestRegions.Dispose();
                HOperatorSet.SelectShapeStd(ho_RegionXLD, out ho_BiggestRegions, "max_area",
                    70);
                //HOperatorSet.DispObj(ho_BiggestRegions, GeoMethod.hv_ExpDefaultWinHandle);
                // MessageBox.Show("最大");
                HOperatorSet.AreaCenter(ho_BiggestRegions, out maxArea, out Row, out Col);
                HOperatorSet.CountObj(ho_RegionXLD, out hv_Number);
                HTuple end_val15 = hv_Number;
                HTuple step_val15 = 1;
                for (hv_i = 1; hv_i.Continue(end_val15, step_val15); hv_i = hv_i.TupleAdd(step_val15))
                {
                    ho_RegionSelected.Dispose();
                    HOperatorSet.SelectObj(ho_RegionXLD, out ho_RegionSelected, hv_i);
                    //HOperatorSet.AreaCenter(ho_RegionSelected, out hv_Area, out hv_Row, out hv_Column);
                    HOperatorSet.AreaCenter(ho_RegionSelected, out itemArea, out Row, out Col);
                    if ((int)itemArea < (int)maxArea)
                    {
                        {
                            
                            HObject ExpTmpOutVar_0;
                            HOperatorSet.Difference(ho_BiggestRegions, ho_RegionSelected, out ExpTmpOutVar_0 );
                            ho_BiggestRegions.Dispose();
                            ho_BiggestRegions = ExpTmpOutVar_0;
                            //MessageBox.Show("操作");
                            //HOperatorSet.DispObj(ho_BiggestRegions, GeoMethod.hv_ExpDefaultWinHandle);
                            //HOperatorSet.AreaCenter(ho_BiggestRegions, out Area, out Row, out Col);
                        }
                    }
                }
                
                ho_BinImage.Dispose();
                
                HOperatorSet.RegionToBin(ho_BiggestRegions, out ho_BinImage, 0, 255, hv_Width,hv_Height);
                HOperatorSet.SetColor(windowHandle, "yellow");
            }
            
          
            ho_ModelContours.Dispose();
            ho_TransContours.Dispose();
            ho_RegionXLD.Dispose();
            ho_ImageReduced.Dispose();
            ho_BiggestRegions.Dispose();
            ho_RegionSelected.Dispose();

            return;
        }

        public static   void Add_new_drawing_object(HTuple hv_Type, HTuple hv_WindowHandle, out HTuple hv_DrawID)
        {


            // Initialize local and output iconic variables 
            hv_DrawID = new HTuple();
            //Create a drawing object DrawID of the specified Type
            //and attach it to the graphics window WindowHandle
            //
            if ((int)(new HTuple(hv_Type.TupleEqual("rectangle1"))) != 0)
            {
                HOperatorSet.CreateDrawingObjectRectangle1(100, 100, 200, 200, out hv_DrawID);
                HOperatorSet.AttachDrawingObjectToWindow(hv_WindowHandle, hv_DrawID);
            }
            else if ((int)(new HTuple(hv_Type.TupleEqual("circle"))) != 0)
            {
                HOperatorSet.CreateDrawingObjectCircle(200, 200, 120, out hv_DrawID);
                HOperatorSet.AttachDrawingObjectToWindow(hv_WindowHandle, hv_DrawID);
            }
            else if ((int)(new HTuple(hv_Type.TupleEqual("rectangle2"))) != 0)
            {
                HOperatorSet.CreateDrawingObjectRectangle2(200, 200, 0, 100, 100, out hv_DrawID);
                HOperatorSet.AttachDrawingObjectToWindow(hv_WindowHandle, hv_DrawID);
            }
            else if ((int)(new HTuple(hv_Type.TupleEqual("ellipse"))) != 0)
            {
                HOperatorSet.CreateDrawingObjectEllipse(200, 200, 0, 100, 60, out hv_DrawID);
                HOperatorSet.AttachDrawingObjectToWindow(hv_WindowHandle, hv_DrawID);
            }
            else if ((int)(new HTuple(hv_Type.TupleEqual("line"))) != 0)
            {
                HOperatorSet.CreateDrawingObjectLine(200, 200, 100, 60, out hv_DrawID);
                HOperatorSet.AttachDrawingObjectToWindow(hv_WindowHandle, hv_DrawID);
            }
            else
            {
                throw new HalconException(
                    (new HTuple("Unrecognized drawing object type.")).TupleConcat("Either not a valid type or not supported by this procedure"));
            }

            return;
        }

        public static   void Process_image(HObject ho_Image, out HObject ho_EdgeAmplitude, HTuple hv_WindowHandle, HTuple hv_DrawID)
        {
            // Local iconic variables 

            HObject ho_Region, ho_ImageReduced;
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_EdgeAmplitude);
            HOperatorSet.GenEmptyObj(out ho_Region);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            try
            {
                //Apply an Sobel edge filter on the background
                //image within the region of interest defined
                //by the drawing object.
                ho_Region.Dispose();
                HOperatorSet.GetDrawingObjectIconic(out ho_Region, hv_DrawID);
                ho_ImageReduced.Dispose();
                HOperatorSet.ReduceDomain(ho_Image, ho_Region, out ho_ImageReduced);
                ho_EdgeAmplitude.Dispose();
                HOperatorSet.SobelAmp(ho_ImageReduced, out ho_EdgeAmplitude, "sum_abs", 3);
                ho_Region.Dispose();
                ho_ImageReduced.Dispose();

                return;
            }
            catch (HalconException HDevExpDefaultException)
            {
                ho_Region.Dispose();
                ho_ImageReduced.Dispose();

                throw HDevExpDefaultException;
            }
        }

      
        public static   void Disp_linelen(HTuple hv_CentreRows, HTuple windowHandle,HTuple hv_CentreCols, HTuple hv_WindowHandle)
        {
            // Local iconic variables 

            // Local control variables 

            HTuple hv_ColorMode = null, hv_step = null;
            HTuple hv_i = null, hv_Distance = new HTuple(), hv_disp_row = new HTuple();
            HTuple hv_disp_col = new HTuple();
            // Initialize local and output iconic variables 
            hv_ColorMode = new HTuple();
            hv_ColorMode[0] = "red";
            hv_ColorMode[1] = "green";
            hv_ColorMode[2] = "yellow";
            hv_ColorMode[3] = "blue";
            hv_step = 30;
            for (hv_i = 0; (int)hv_i <= (int)((new HTuple(hv_CentreRows.TupleLength())) - 2); hv_i = (int)hv_i + 1)
            {
                HOperatorSet.SetDraw(windowHandle, "fill");
                HOperatorSet.SetColor(windowHandle, hv_ColorMode.TupleSelect(hv_i % (new HTuple(hv_ColorMode.TupleLength()
                    ))));
                HOperatorSet.DispLine(windowHandle, hv_CentreRows.TupleSelect(hv_i),
                    hv_CentreCols.TupleSelect(hv_i), hv_CentreRows.TupleSelect(hv_i + 1), hv_CentreCols.TupleSelect(
                    hv_i + 1));
                HOperatorSet.DistancePp(hv_CentreRows.TupleSelect(hv_i), hv_CentreCols.TupleSelect(
                    hv_i), hv_CentreRows.TupleSelect(hv_i + 1), hv_CentreCols.TupleSelect(hv_i + 1),
                    out hv_Distance);
                hv_disp_row = ((hv_CentreRows.TupleSelect(hv_i)) + (hv_CentreRows.TupleSelect(
                    hv_i + 1))) / 2;
                hv_disp_col = (((hv_CentreCols.TupleSelect(hv_i)) + (hv_CentreCols.TupleSelect(
                    hv_i + 1))) / 2) + hv_step;

                HOperatorSet.DispLine(windowHandle, hv_CentreRows.TupleSelect(hv_i),
                    hv_CentreCols.TupleSelect(hv_i), hv_disp_row, hv_disp_col);
                HOperatorSet.DispLine(windowHandle, hv_CentreRows.TupleSelect(hv_i + 1),
                    hv_CentreCols.TupleSelect(hv_i + 1), hv_disp_row, hv_disp_col);

                HOperatorSet.DispText(windowHandle, "" + hv_Distance, "image", hv_disp_row,
                    hv_disp_col, "black", new HTuple(), new HTuple());
            }

            return;
        }

        public static   void Get_hommat2d(HTuple hv_Angle, HTuple hv_Row, HTuple hv_Column, out HTuple hv_HomMat2D)
        {
            // Initialize local and output iconic variables 
            HOperatorSet.HomMat2dIdentity(out hv_HomMat2D);
            HOperatorSet.HomMat2dRotate(hv_HomMat2D, hv_Angle, 0, 0, out hv_HomMat2D);
            HOperatorSet.HomMat2dTranslate(hv_HomMat2D, hv_Row, hv_Column, out hv_HomMat2D);
            return;
        }


         public static   void Measure_line(HObject ho_Sample,HTuple windowHandle, HTuple hv_LineRowStart_Measure, HTuple hv_LineColumnStart_Measure,
         HTuple hv_LineRowEnd_Measure, HTuple hv_LineColumnEnd_Measure, HTuple hv_AmplitudeThreshold,
         HTuple hv_RoiWidthLen, HTuple hv_WindowHandle, HTuple hv_Angle, HTuple hv_Mode,
         HTuple hv_select, out HTuple hv_Row_Measure, out HTuple hv_Column_Measure, out HTuple hv_Amplitude_Measure,
         out HTuple hv_Distance_Measure, out HTuple hv_Draw_IDArray)
        {

            // Local control variables 
            HTuple hv_ColorMode = null, hv_Rate = new HTuple();
            HTuple hv_TmpCtrl_Row = new HTuple(), hv_TmpCtrl_Column = new HTuple();
            HTuple hv_TmpCtrl_Dr = new HTuple(), hv_TmpCtrl_Dc = new HTuple();
            HTuple hv_TmpCtrl_Phi = new HTuple(), hv_TmpCtrl_Len1 = new HTuple();
            HTuple hv_TmpCtrl_Len2 = new HTuple(), hv_Width = new HTuple(), hv_Height = new HTuple();
            HTuple hv_MsrHandle_Measure = new HTuple(), hv_RowEdgeFirst = new HTuple();
            HTuple hv_ColumnEdgeFirst = new HTuple(), hv_AmplitudeFirst = new HTuple();
            HTuple hv_RowEdgeSecond = new HTuple(), hv_ColumnEdgeSecond = new HTuple();
            HTuple hv_AmplitudeSecond = new HTuple(), hv_IntraDistance = new HTuple();
            HTuple hv_InterDistance = new HTuple(), hv_i = new HTuple(), hv_step = new HTuple();
            HTuple hv_DrawID3 = new HTuple(), hv_Distance = new HTuple();
            HTuple hv_disp_row = new HTuple(), hv_disp_col = new HTuple();
            // Initialize local and output iconic variables 
            //*AmplitudeThreshold := 40
            //*RoiWidthLen2 := 5
            //*LineRowStart_Measure := Rol1
            //*LineColumnStart_Measure := Col1
            //*LineRowEnd_Measure := Rol2
            //*LineColumnEnd_Measure:= Col2
            hv_ColorMode = new HTuple();
            hv_ColorMode[0] = "red";
            hv_ColorMode[1] = "green";
            hv_ColorMode[2] = "yellow";
            hv_ColorMode[3] = "blue";
            hv_Draw_IDArray = new HTuple();
            if ((int)(new HTuple(hv_Mode.TupleEqual("extend"))) != 0)
            {
                hv_Rate = 1.5;
                hv_TmpCtrl_Row = hv_LineRowStart_Measure.Clone();
                hv_TmpCtrl_Column = hv_LineColumnStart_Measure.Clone();
                hv_TmpCtrl_Dr = hv_LineRowStart_Measure - hv_LineRowEnd_Measure;
                hv_TmpCtrl_Dc = hv_LineColumnEnd_Measure - hv_LineColumnStart_Measure;
                hv_TmpCtrl_Phi = hv_TmpCtrl_Dr.TupleAtan2(hv_TmpCtrl_Dc);
                hv_TmpCtrl_Len1 = hv_Rate * ((((hv_TmpCtrl_Dr * hv_TmpCtrl_Dr) + (hv_TmpCtrl_Dc * hv_TmpCtrl_Dc))).TupleSqrt() );
            }
            else
            {
                hv_Rate = 0.5;
                hv_TmpCtrl_Row = 0.5 * (hv_LineRowStart_Measure + hv_LineRowEnd_Measure);
                hv_TmpCtrl_Column = 0.5 * (hv_LineColumnStart_Measure + hv_LineColumnEnd_Measure);
                hv_TmpCtrl_Dr = hv_LineRowStart_Measure - hv_LineRowEnd_Measure;
                hv_TmpCtrl_Dc = hv_LineColumnEnd_Measure - hv_LineColumnStart_Measure;
                hv_TmpCtrl_Phi = hv_TmpCtrl_Dr.TupleAtan2(hv_TmpCtrl_Dc);
                hv_TmpCtrl_Len1 = hv_Rate * ((((hv_TmpCtrl_Dr * hv_TmpCtrl_Dr) + (hv_TmpCtrl_Dc * hv_TmpCtrl_Dc))).TupleSqrt() );
            }

            hv_TmpCtrl_Len2 = hv_RoiWidthLen.Clone();
          

            HOperatorSet.GetImageSize(ho_Sample, out hv_Width, out hv_Height);
            HOperatorSet.GenMeasureRectangle2(hv_TmpCtrl_Row, hv_TmpCtrl_Column, hv_TmpCtrl_Phi,
                hv_TmpCtrl_Len1, hv_TmpCtrl_Len2, hv_Width, hv_Height, "nearest_neighbor",
                out hv_MsrHandle_Measure);

            //*指定为positive时intra distance代表几个孔的内部直径，interdistance代表几个孔之间的距离
            HOperatorSet.MeasurePairs(ho_Sample, hv_MsrHandle_Measure, 1, 30, "positive",
                "all", out hv_RowEdgeFirst, out hv_ColumnEdgeFirst, out hv_AmplitudeFirst,
                out hv_RowEdgeSecond, out hv_ColumnEdgeSecond, out hv_AmplitudeSecond, out hv_IntraDistance,
                out hv_InterDistance);


            for (hv_i = 0; (int)hv_i <= (int)((new HTuple(hv_RowEdgeFirst.TupleLength())) - 1); hv_i = (int)hv_i + 1)
            {
                HOperatorSet.SetColor(windowHandle, hv_ColorMode.TupleSelect(hv_i % (new HTuple(hv_ColorMode.TupleLength() ))));
                HOperatorSet.DispLine(windowHandle, hv_RowEdgeFirst.TupleSelect(hv_i),hv_ColumnEdgeFirst.TupleSelect(hv_i), hv_RowEdgeSecond.TupleSelect(hv_i), hv_ColumnEdgeSecond.TupleSelect(hv_i));
            }
            

            HOperatorSet.MeasurePos(ho_Sample, hv_MsrHandle_Measure, 1, hv_AmplitudeThreshold,"all", "all", out hv_Row_Measure, out hv_Column_Measure, out hv_Amplitude_Measure,out hv_Distance_Measure);
            hv_step = 30;
            for (hv_i = 0; (int)hv_i <= (int)((new HTuple(hv_Row_Measure.TupleLength())) - 1); hv_i = (int)hv_i + 1)
            {
                HOperatorSet.SetColor(windowHandle, hv_ColorMode.TupleSelect(hv_i % (new HTuple(hv_ColorMode.TupleLength() ))));
                HOperatorSet.CreateDrawingObjectCircle(hv_Row_Measure.TupleSelect(hv_i), hv_Column_Measure.TupleSelect(hv_i), 1, out hv_DrawID3);
                hv_Draw_IDArray = hv_Draw_IDArray.TupleConcat(hv_DrawID3);
                HOperatorSet.AttachDrawingObjectToWindow(windowHandle, hv_DrawID3);
                if ((int)(new HTuple(hv_i.TupleLess((new HTuple(hv_Row_Measure.TupleLength() )) - 1))) != 0)
                {
                    HOperatorSet.DispLine(windowHandle, hv_Row_Measure.TupleSelect(hv_i), hv_Column_Measure.TupleSelect(hv_i), hv_Row_Measure.TupleSelect(hv_i + 1), hv_Column_Measure.TupleSelect(hv_i + 1));
                    HOperatorSet.DistancePp(hv_Row_Measure.TupleSelect(hv_i), hv_Column_Measure.TupleSelect( hv_i), hv_Row_Measure.TupleSelect(hv_i + 1), hv_Column_Measure.TupleSelect(hv_i + 1), out hv_Distance);
                    hv_disp_row = ((hv_Row_Measure.TupleSelect(hv_i)) + (hv_Row_Measure.TupleSelect(hv_i + 1))) / 2;
                    hv_disp_col = (((hv_Column_Measure.TupleSelect(hv_i)) + (hv_Column_Measure.TupleSelect(hv_i + 1))) / 2) + hv_step;
                    HOperatorSet.SetColor(windowHandle, "white");
                    HOperatorSet.DispLine(windowHandle, hv_Row_Measure.TupleSelect(hv_i), hv_Column_Measure.TupleSelect(hv_i), hv_disp_row, hv_disp_col);
                    HOperatorSet.DispLine(windowHandle, hv_Row_Measure.TupleSelect(hv_i + 1), hv_Column_Measure.TupleSelect(hv_i + 1), hv_disp_row, hv_disp_col);
                    HOperatorSet.DispText(windowHandle, "" + hv_Distance, "image", hv_disp_row, hv_disp_col, "black", new HTuple(), new HTuple());
                }

            }
            HOperatorSet.CloseMeasure(hv_MsrHandle_Measure);

            return;
        }


        public static   void Trans_contours(HObject ho_ModelContours,HTuple windowHandle, out HObject ho_TransContours, HTuple hv_Angle, HTuple hv_Row, HTuple hv_Column)
        {
            // Local control variables 

            HTuple hv_HomMat2D = null;
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_TransContours);
            HOperatorSet.HomMat2dIdentity(out hv_HomMat2D);
            HOperatorSet.HomMat2dRotate(hv_HomMat2D, hv_Angle, 0, 0, out hv_HomMat2D);
            HOperatorSet.HomMat2dTranslate(hv_HomMat2D, hv_Row, hv_Column, out hv_HomMat2D);
            ho_TransContours.Dispose();
            HOperatorSet.AffineTransContourXld(ho_ModelContours, out ho_TransContours, hv_HomMat2D);
         //   HOperatorSet.SetColor(windowHandle, "green");
           // HOperatorSet.DispObj(ho_TransContours, windowHandle);

            return;
        }

        public static   Point Get_peakPoint_fromROI(HObject ho_Image,HObject ROI, HTuple windowHandle, HTuple hv_Mode, HTuple Threshold1, HTuple Threshold2,string pointName)
        {
            Point peakPoint;

            HObject ho_Contours, ho_CentreLine, ho_CentreLineContour;
            HObject ho_ParallelContours, ho_ImageReduced, ho_ImageBinomial;
            HObject ho_Region, ho_RegionErosion, ho_RegionDilation;
            HObject ho_RegionBorder, ho_Skeleton, ho_Contours1, ho_ObjectSelected = null;

            HTuple hv_PeakNearRow = 0, hv_PeakNearCol = 0, hv_PeakLongRow = 0, hv_PeakLongCol = 0;
            HTuple hv_pi = null, hv_Row = null, hv_Column = null;
            HTuple hv_Phi = null, hv_Length1 = null, hv_Length2 = null;
            HTuple hv_PointOrder = null, hv_Col = null, hv_rmin = null;
            HTuple hv_rmax = null, hv_cmin = null, hv_cmax = null;
            HTuple hv_RowBegin = null, hv_RowEnd = null, hv_ColBegin = null;
            HTuple hv_ColEnd = null;
            HTuple hv_Number = null, hv_i = null, hv_maxDist = null;
            HTuple hv_minDist = null, hv_maxIndex = null, hv_minIndex = null;
            HTuple hv_Rows = new HTuple(), hv_Cols = new HTuple();
            HTuple hv_Distance = new HTuple(), hv_j = new HTuple();

            HOperatorSet.GenEmptyObj(out ho_Contours);
            HOperatorSet.GenEmptyObj(out ho_CentreLine);
            HOperatorSet.GenEmptyObj(out ho_CentreLineContour);
            HOperatorSet.GenEmptyObj(out ho_ParallelContours);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            HOperatorSet.GenEmptyObj(out ho_ImageBinomial);
            HOperatorSet.GenEmptyObj(out ho_Region);
            HOperatorSet.GenEmptyObj(out ho_RegionErosion);
            HOperatorSet.GenEmptyObj(out ho_RegionDilation);
            HOperatorSet.GenEmptyObj(out ho_RegionBorder);
            HOperatorSet.GenEmptyObj(out ho_Skeleton);
            HOperatorSet.GenEmptyObj(out ho_Contours1);
            HOperatorSet.GenEmptyObj(out ho_ObjectSelected);
            try
            {
                hv_pi = ((new HTuple(0)).TupleAcos()) * 2;
                ho_Contours.Dispose();
                HOperatorSet.GenContourRegionXld(ROI, out ho_Contours, "border");
                HOperatorSet.FitRectangle2ContourXld(ho_Contours, "regression", -1, 0, 0, 3,
                    2, out hv_Row, out hv_Column, out hv_Phi, out hv_Length1, out hv_Length2,
                    out hv_PointOrder);

                ho_CentreLine.Dispose();
                HOperatorSet.GenRectangle2(out ho_CentreLine, hv_Row, hv_Column, hv_Phi, hv_Length1, 1);
                {
                    HObject ExpTmpOutVar_0;
                    HOperatorSet.Skeleton(ho_CentreLine, out ExpTmpOutVar_0);
                    ho_CentreLine.Dispose();
                    ho_CentreLine = ExpTmpOutVar_0;
                }
                ho_CentreLineContour.Dispose();
                HOperatorSet.GenContourRegionXld(ho_CentreLine, out ho_CentreLineContour, "center");
                ho_ParallelContours.Dispose();
                HOperatorSet.GenParallelContourXld(ho_CentreLineContour, out ho_ParallelContours,
                    "regression_normal", hv_Length2);
                HOperatorSet.GetContourXld(ho_ParallelContours, out hv_Row, out hv_Col);
                HOperatorSet.TupleMin(hv_Row, out hv_rmin);
                HOperatorSet.TupleMax(hv_Row, out hv_rmax);
                HOperatorSet.TupleMin(hv_Col, out hv_cmin);
                HOperatorSet.TupleMax(hv_Col, out hv_cmax);

                hv_RowBegin = 0;
                hv_RowEnd = 0;
                hv_ColBegin = 0;
                hv_ColEnd = 0;
                if ((int)(new HTuple(hv_Phi.TupleLess(0))) != 0)
                {
                    hv_Phi = hv_Phi + (2 * hv_pi);
                }
                if ((int)((new HTuple((new HTuple(hv_Phi.TupleGreater(0))).TupleAnd(new HTuple(hv_Phi.TupleLess(
                    0.5 * hv_pi))))).TupleOr((new HTuple(hv_Phi.TupleGreater(hv_pi))).TupleAnd(
                    new HTuple(hv_Phi.TupleLess(1.5 * hv_pi))))) != 0)
                {
                    hv_RowBegin = hv_rmax.Clone();
                    hv_RowEnd = hv_rmin.Clone();
                    hv_ColBegin = hv_cmin.Clone();
                    hv_ColEnd = hv_cmax.Clone();
                }
                else if ((int)((new HTuple(hv_Phi.TupleEqual(0.5 * hv_pi))).TupleOr(new HTuple(hv_Phi.TupleEqual(
                    1.5 * hv_pi)))) != 0)
                {
                    hv_ColBegin = 0.5 * (hv_cmax + hv_cmin);
                    hv_ColEnd = hv_ColBegin.Clone();
                    hv_RowBegin = hv_rmin.Clone();
                    hv_RowEnd = hv_rmax.Clone();
                }
                else if ((int)((new HTuple(hv_Phi.TupleEqual(0))).TupleOr(new HTuple(hv_Phi.TupleEqual(
                    hv_pi)))) != 0)
                {
                    hv_RowBegin = 0.5 * (hv_rmax + hv_rmin);
                    hv_RowEnd = hv_RowBegin.Clone();
                    hv_ColBegin = hv_cmin.Clone();
                    hv_ColEnd = hv_cmax.Clone();
                }
                else
                {
                    hv_RowBegin = hv_rmin.Clone();
                    hv_RowEnd = hv_rmax.Clone();
                    hv_ColBegin = hv_cmin.Clone();
                    hv_ColEnd = hv_cmax.Clone();
                }



                ho_ImageReduced.Dispose();
                HOperatorSet.ReduceDomain(ho_Image, ROI, out ho_ImageReduced);
                ho_ImageBinomial.Dispose();
                HOperatorSet.BinomialFilter(ho_ImageReduced, out ho_ImageBinomial, 5, 5);


                ho_Region.Dispose();
                //HOperatorSet.BinaryThreshold(ho_ImageBinomial, out ho_Region, "max_separability", "dark", out hv_UsedThreshold);
                HOperatorSet.Threshold(ho_Image, out ho_Region, Threshold1, Threshold2);
                ho_RegionErosion.Dispose();
                HOperatorSet.ErosionCircle(ho_Region, out ho_RegionErosion, 3.5);
                ho_RegionDilation.Dispose();
                HOperatorSet.DilationCircle(ho_RegionErosion, out ho_RegionDilation, 3.5);

                ho_RegionBorder.Dispose();
                HOperatorSet.Boundary(ho_RegionErosion, out ho_RegionBorder, "inner");
                ho_Skeleton.Dispose();
                HOperatorSet.Skeleton(ho_RegionBorder, out ho_Skeleton);
                ho_Contours1.Dispose();
                HOperatorSet.GenContourRegionXld(ho_Skeleton, out ho_Contours1, "border");
                HOperatorSet.CountObj(ho_Contours1, out hv_Number);


                hv_maxDist = 0;
                hv_minDist = 9999;
                hv_maxIndex = 0;
                hv_minIndex = 0;
                HTuple end_val = hv_Number;
                HTuple step_val = 1;
                for (hv_i = 1; hv_i.Continue(end_val, step_val); hv_i = hv_i.TupleAdd(step_val))
                {
                    ho_ObjectSelected.Dispose();
                    HOperatorSet.SelectObj(ho_Contours1, out ho_ObjectSelected, hv_i);
                    HOperatorSet.GetContourXld(ho_ObjectSelected, out hv_Rows, out hv_Cols);
                    HOperatorSet.SetColor(windowHandle, "yellow");
                    HOperatorSet.SetLineWidth(windowHandle, 3);
                    HOperatorSet.DistancePl(hv_Rows, hv_Cols, hv_RowBegin, hv_ColBegin, hv_RowEnd, hv_ColEnd, out hv_Distance);
                    for (hv_j = 1; (int)hv_j <= (int)((new HTuple(hv_Distance.TupleLength())) - 1); hv_j = (int)hv_j + 1)
                    {
                        if ((int)(new HTuple(((hv_Distance.TupleSelect(hv_j))).TupleGreater(hv_maxDist))) != 0)
                        {
                            hv_maxDist = hv_Distance.TupleSelect(hv_j);
                            hv_maxIndex = hv_j.Clone();
                            hv_PeakLongRow = hv_Rows.TupleSelect(hv_maxIndex);
                            hv_PeakLongCol = hv_Cols.TupleSelect(hv_maxIndex);
                        }
                        if ((int)(new HTuple(((hv_Distance.TupleSelect(hv_j))).TupleLess(hv_minDist))) != 0)
                        {
                            hv_minDist = hv_Distance.TupleSelect(hv_j);
                            hv_minIndex = hv_j.Clone();
                            hv_PeakNearRow = hv_Rows.TupleSelect(hv_minIndex);
                            hv_PeakNearCol = hv_Cols.TupleSelect(hv_minIndex);
                        }
                    }

                }

                ho_Contours.Dispose();
                ho_CentreLine.Dispose();
                ho_CentreLineContour.Dispose();
                ho_ParallelContours.Dispose();
                ho_ImageReduced.Dispose();
                ho_ImageBinomial.Dispose();
                ho_Region.Dispose();
                ho_RegionErosion.Dispose();
                ho_RegionDilation.Dispose();
                ho_RegionBorder.Dispose();
                ho_Skeleton.Dispose();
                ho_Contours1.Dispose();
                ho_ObjectSelected.Dispose();
                if (hv_Mode == "neighbor")
                {
                    peakPoint = new Point(hv_PeakNearRow, hv_PeakNearCol,pointName);
                    HOperatorSet.SetColor(windowHandle, "blue");
                    HOperatorSet.DispCircle(windowHandle, hv_PeakNearRow, hv_PeakNearCol, 5.0);
                }
                else if (hv_Mode == "longest")
                {
                    peakPoint = new Point(hv_PeakLongRow, hv_PeakLongCol, pointName);
                    HOperatorSet.SetColor(windowHandle, "blue");
                    HOperatorSet.DispCircle(windowHandle, hv_PeakLongRow, hv_PeakLongCol, 5.0);
                }
                else
                {
                    MessageBox.Show("异常");
                    return null;
                }

            }
            catch (Exception)
            {
                ho_Contours.Dispose();
                ho_CentreLine.Dispose();
                ho_CentreLineContour.Dispose();
                ho_ParallelContours.Dispose();
                ho_ImageReduced.Dispose();
                ho_ImageBinomial.Dispose();
                ho_Region.Dispose();
                ho_RegionErosion.Dispose();
                ho_RegionDilation.Dispose();
                ho_RegionBorder.Dispose();
                ho_Skeleton.Dispose();
                ho_Contours1.Dispose();
                ho_ObjectSelected.Dispose();
                throw new Exception();
            }
            return peakPoint;
        }

        public static   Point Get_peakPoint_fromROI(HObject ho_Image, HObject ROI, HTuple windowHandle, HTuple hv_Mode, HTuple Threshold1, HTuple Threshold2)
        {
            Point peakPoint;

            HObject ho_Contours, ho_CentreLine, ho_CentreLineContour;
            HObject ho_ParallelContours, ho_ImageReduced, ho_ImageBinomial;
            HObject ho_Region, ho_RegionErosion, ho_RegionDilation;
            HObject ho_RegionBorder, ho_Skeleton, ho_Contours1, ho_ObjectSelected = null;

            HTuple hv_PeakNearRow = 0, hv_PeakNearCol = 0, hv_PeakLongRow = 0, hv_PeakLongCol = 0;
            HTuple hv_pi = null, hv_Row = null, hv_Column = null;
            HTuple hv_Phi = null, hv_Length1 = null, hv_Length2 = null;
            HTuple hv_PointOrder = null, hv_Col = null, hv_rmin = null;
            HTuple hv_rmax = null, hv_cmin = null, hv_cmax = null;
            HTuple hv_RowBegin = null, hv_RowEnd = null, hv_ColBegin = null;
            HTuple hv_ColEnd = null;
            HTuple hv_Number = null, hv_i = null, hv_maxDist = null;
            HTuple hv_minDist = null, hv_maxIndex = null, hv_minIndex = null;
            HTuple hv_Rows = new HTuple(), hv_Cols = new HTuple();
            HTuple hv_Distance = new HTuple(), hv_j = new HTuple();

            HOperatorSet.GenEmptyObj(out ho_Contours);
            HOperatorSet.GenEmptyObj(out ho_CentreLine);
            HOperatorSet.GenEmptyObj(out ho_CentreLineContour);
            HOperatorSet.GenEmptyObj(out ho_ParallelContours);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            HOperatorSet.GenEmptyObj(out ho_ImageBinomial);
            HOperatorSet.GenEmptyObj(out ho_Region);
            HOperatorSet.GenEmptyObj(out ho_RegionErosion);
            HOperatorSet.GenEmptyObj(out ho_RegionDilation);
            HOperatorSet.GenEmptyObj(out ho_RegionBorder);
            HOperatorSet.GenEmptyObj(out ho_Skeleton);
            HOperatorSet.GenEmptyObj(out ho_Contours1);
            HOperatorSet.GenEmptyObj(out ho_ObjectSelected);
            try
            {
                hv_pi = ((new HTuple(0)).TupleAcos()) * 2;
                ho_Contours.Dispose();
                HOperatorSet.GenContourRegionXld(ROI, out ho_Contours, "border");
                HOperatorSet.FitRectangle2ContourXld(ho_Contours, "regression", -1, 0, 0, 3,
                    2, out hv_Row, out hv_Column, out hv_Phi, out hv_Length1, out hv_Length2,
                    out hv_PointOrder);

                ho_CentreLine.Dispose();
                HOperatorSet.GenRectangle2(out ho_CentreLine, hv_Row, hv_Column, hv_Phi, hv_Length1, 1);
                {
                    HObject ExpTmpOutVar_0;
                    HOperatorSet.Skeleton(ho_CentreLine, out ExpTmpOutVar_0);
                    ho_CentreLine.Dispose();
                    ho_CentreLine = ExpTmpOutVar_0;
                }
                ho_CentreLineContour.Dispose();
                HOperatorSet.GenContourRegionXld(ho_CentreLine, out ho_CentreLineContour, "center");
                ho_ParallelContours.Dispose();
                HOperatorSet.GenParallelContourXld(ho_CentreLineContour, out ho_ParallelContours,
                    "regression_normal", hv_Length2);
                HOperatorSet.GetContourXld(ho_ParallelContours, out hv_Row, out hv_Col);
                HOperatorSet.TupleMin(hv_Row, out hv_rmin);
                HOperatorSet.TupleMax(hv_Row, out hv_rmax);
                HOperatorSet.TupleMin(hv_Col, out hv_cmin);
                HOperatorSet.TupleMax(hv_Col, out hv_cmax);

                hv_RowBegin = 0;
                hv_RowEnd = 0;
                hv_ColBegin = 0;
                hv_ColEnd = 0;
                if ((int)(new HTuple(hv_Phi.TupleLess(0))) != 0)
                {
                    hv_Phi = hv_Phi + (2 * hv_pi);
                }
                if ((int)((new HTuple((new HTuple(hv_Phi.TupleGreater(0))).TupleAnd(new HTuple(hv_Phi.TupleLess(
                    0.5 * hv_pi))))).TupleOr((new HTuple(hv_Phi.TupleGreater(hv_pi))).TupleAnd(
                    new HTuple(hv_Phi.TupleLess(1.5 * hv_pi))))) != 0)
                {
                    hv_RowBegin = hv_rmax.Clone();
                    hv_RowEnd = hv_rmin.Clone();
                    hv_ColBegin = hv_cmin.Clone();
                    hv_ColEnd = hv_cmax.Clone();
                }
                else if ((int)((new HTuple(hv_Phi.TupleEqual(0.5 * hv_pi))).TupleOr(new HTuple(hv_Phi.TupleEqual(
                    1.5 * hv_pi)))) != 0)
                {
                    hv_ColBegin = 0.5 * (hv_cmax + hv_cmin);
                    hv_ColEnd = hv_ColBegin.Clone();
                    hv_RowBegin = hv_rmin.Clone();
                    hv_RowEnd = hv_rmax.Clone();
                }
                else if ((int)((new HTuple(hv_Phi.TupleEqual(0))).TupleOr(new HTuple(hv_Phi.TupleEqual(
                    hv_pi)))) != 0)
                {
                    hv_RowBegin = 0.5 * (hv_rmax + hv_rmin);
                    hv_RowEnd = hv_RowBegin.Clone();
                    hv_ColBegin = hv_cmin.Clone();
                    hv_ColEnd = hv_cmax.Clone();
                }
                else
                {
                    hv_RowBegin = hv_rmin.Clone();
                    hv_RowEnd = hv_rmax.Clone();
                    hv_ColBegin = hv_cmin.Clone();
                    hv_ColEnd = hv_cmax.Clone();
                }



                ho_ImageReduced.Dispose();
                HOperatorSet.ReduceDomain(ho_Image, ROI, out ho_ImageReduced);
                ho_ImageBinomial.Dispose();
                HOperatorSet.BinomialFilter(ho_ImageReduced, out ho_ImageBinomial, 5, 5);


                ho_Region.Dispose();
                //HOperatorSet.BinaryThreshold(ho_ImageBinomial, out ho_Region, "max_separability", "dark", out hv_UsedThreshold);
                HOperatorSet.Threshold(ho_Image, out ho_Region, Threshold1, Threshold2);
                ho_RegionErosion.Dispose();
                HOperatorSet.ErosionCircle(ho_Region, out ho_RegionErosion, 3.5);
                ho_RegionDilation.Dispose();
                HOperatorSet.DilationCircle(ho_RegionErosion, out ho_RegionDilation, 3.5);

                ho_RegionBorder.Dispose();
                HOperatorSet.Boundary(ho_RegionErosion, out ho_RegionBorder, "inner");
                ho_Skeleton.Dispose();
                HOperatorSet.Skeleton(ho_RegionBorder, out ho_Skeleton);
                ho_Contours1.Dispose();
                HOperatorSet.GenContourRegionXld(ho_Skeleton, out ho_Contours1, "border");
                HOperatorSet.CountObj(ho_Contours1, out hv_Number);


                hv_maxDist = 0;
                hv_minDist = 9999;
                hv_maxIndex = 0;
                hv_minIndex = 0;
                HTuple end_val = hv_Number;
                HTuple step_val = 1;
                for (hv_i = 1; hv_i.Continue(end_val, step_val); hv_i = hv_i.TupleAdd(step_val))
                {
                    ho_ObjectSelected.Dispose();
                    HOperatorSet.SelectObj(ho_Contours1, out ho_ObjectSelected, hv_i);
                    HOperatorSet.GetContourXld(ho_ObjectSelected, out hv_Rows, out hv_Cols);
                    HOperatorSet.SetColor(windowHandle, "yellow");
                    HOperatorSet.SetLineWidth(windowHandle, 3);
                    HOperatorSet.DistancePl(hv_Rows, hv_Cols, hv_RowBegin, hv_ColBegin, hv_RowEnd, hv_ColEnd, out hv_Distance);
                    for (hv_j = 1; (int)hv_j <= (int)((new HTuple(hv_Distance.TupleLength())) - 1); hv_j = (int)hv_j + 1)
                    {
                        if ((int)(new HTuple(((hv_Distance.TupleSelect(hv_j))).TupleGreater(hv_maxDist))) != 0)
                        {
                            hv_maxDist = hv_Distance.TupleSelect(hv_j);
                            hv_maxIndex = hv_j.Clone();
                            hv_PeakLongRow = hv_Rows.TupleSelect(hv_maxIndex);
                            hv_PeakLongCol = hv_Cols.TupleSelect(hv_maxIndex);
                        }
                        if ((int)(new HTuple(((hv_Distance.TupleSelect(hv_j))).TupleLess(hv_minDist))) != 0)
                        {
                            hv_minDist = hv_Distance.TupleSelect(hv_j);
                            hv_minIndex = hv_j.Clone();
                            hv_PeakNearRow = hv_Rows.TupleSelect(hv_minIndex);
                            hv_PeakNearCol = hv_Cols.TupleSelect(hv_minIndex);
                        }
                    }

                }

                ho_Contours.Dispose();
                ho_CentreLine.Dispose();
                ho_CentreLineContour.Dispose();
                ho_ParallelContours.Dispose();
                ho_ImageReduced.Dispose();
                ho_ImageBinomial.Dispose();
                ho_Region.Dispose();
                ho_RegionErosion.Dispose();
                ho_RegionDilation.Dispose();
                ho_RegionBorder.Dispose();
                ho_Skeleton.Dispose();
                ho_Contours1.Dispose();
                ho_ObjectSelected.Dispose();
                if (hv_Mode == "neighbor")
                {
                    peakPoint = new Point(hv_PeakNearRow, hv_PeakNearCol);
                    HOperatorSet.SetColor(windowHandle, "blue");
                    HOperatorSet.DispCircle(windowHandle, hv_PeakNearRow, hv_PeakNearCol, 5.0);
                }
                else if (hv_Mode == "longest")
                {
                    peakPoint = new Point(hv_PeakLongRow, hv_PeakLongCol);
                    HOperatorSet.SetColor(windowHandle, "blue");
                    HOperatorSet.DispCircle(windowHandle, hv_PeakLongRow, hv_PeakLongCol, 5.0);
                }
                else
                {
                    MessageBox.Show("异常");
                    return null;
                }

            }
            catch (Exception)
            {
                ho_Contours.Dispose();
                ho_CentreLine.Dispose();
                ho_CentreLineContour.Dispose();
                ho_ParallelContours.Dispose();
                ho_ImageReduced.Dispose();
                ho_ImageBinomial.Dispose();
                ho_Region.Dispose();
                ho_RegionErosion.Dispose();
                ho_RegionDilation.Dispose();
                ho_RegionBorder.Dispose();
                ho_Skeleton.Dispose();
                ho_Contours1.Dispose();
                ho_ObjectSelected.Dispose();
                throw new Exception();
            }
            return peakPoint;
        }

     
        public static   Point Get_point_fromLine(HObject ho_Image, HTuple windowHandle, HTuple hv_Mode, HTuple hv_RowStart, HTuple hv_ColStart, HTuple hv_RowEnd, HTuple hv_ColEnd)
        {
            HTuple hv_PointRow = null, hv_PointCol = null;
            Point rsPoint = null;
            HObject ho_ImageCopy;
            HTuple hv_AmplitudeThreshold = null, hv_RoiWidthLen2 = null;
            HTuple hv_LineRowStart_Measure_01_0 = null, hv_LineColumnStart_Measure_01_0 = null;
            HTuple hv_LineRowEnd_Measure_01_0 = null, hv_LineColumnEnd_Measure_01_0 = null;
            HTuple hv_TmpCtrl_Row = null, hv_TmpCtrl_Column = null;
            HTuple hv_TmpCtrl_Dr = null, hv_TmpCtrl_Dc = null, hv_TmpCtrl_Phi = null;
            HTuple hv_TmpCtrl_Len1 = null, hv_TmpCtrl_Len2 = null;
            HTuple hv_MsrHandle_Measure = null, hv_Row_Measure = null;
            HTuple hv_Column_Measure = null, hv_Amplitude_Measure = null;
            HTuple hv_Distance_Measure = null, hv_Width = null, hv_Height = null;

            HOperatorSet.GenEmptyObj(out ho_ImageCopy);
            hv_PointRow = new HTuple();
            hv_PointCol = new HTuple();
            hv_AmplitudeThreshold = 40;
            hv_RoiWidthLen2 = 5;
            HOperatorSet.SetSystem("int_zooming", "true");
            hv_LineRowStart_Measure_01_0 = hv_RowStart.Clone();
            hv_LineColumnStart_Measure_01_0 = hv_ColStart.Clone();
            hv_LineRowEnd_Measure_01_0 = hv_RowEnd.Clone();
            hv_LineColumnEnd_Measure_01_0 = hv_ColEnd.Clone();

            hv_TmpCtrl_Row = 0.5 * (hv_LineRowStart_Measure_01_0 + hv_LineRowEnd_Measure_01_0);
            hv_TmpCtrl_Column = 0.5 * (hv_LineColumnStart_Measure_01_0 + hv_LineColumnEnd_Measure_01_0);
            hv_TmpCtrl_Dr = hv_LineRowStart_Measure_01_0 - hv_LineRowEnd_Measure_01_0;
            hv_TmpCtrl_Dc = hv_LineColumnEnd_Measure_01_0 - hv_LineColumnStart_Measure_01_0;
            hv_TmpCtrl_Phi = hv_TmpCtrl_Dr.TupleAtan2(hv_TmpCtrl_Dc);
            hv_TmpCtrl_Len1 = 0.5 * ((((hv_TmpCtrl_Dr * hv_TmpCtrl_Dr) + (hv_TmpCtrl_Dc * hv_TmpCtrl_Dc))).TupleSqrt()
                );
            hv_TmpCtrl_Len2 = hv_RoiWidthLen2.Clone();



            HOperatorSet.GetImageSize(ho_Image, out hv_Width, out hv_Height);
            HOperatorSet.GenMeasureRectangle2(hv_TmpCtrl_Row, hv_TmpCtrl_Column, hv_TmpCtrl_Phi,
                hv_TmpCtrl_Len1, hv_TmpCtrl_Len2, hv_Width, hv_Height, "nearest_neighbor", out hv_MsrHandle_Measure);

            ho_ImageCopy.Dispose();
            HOperatorSet.CopyObj(ho_Image, out ho_ImageCopy, 1, 1);
            try
            {
                HOperatorSet.MeasurePos(ho_ImageCopy, hv_MsrHandle_Measure, 1, hv_AmplitudeThreshold,hv_Mode, "first", out hv_Row_Measure, out hv_Column_Measure, out hv_Amplitude_Measure,
                 out hv_Distance_Measure);
                HOperatorSet.CloseMeasure(hv_MsrHandle_Measure);
                if ((int)(new HTuple((new HTuple(hv_Row_Measure.TupleLength())).TupleGreater(0))) != 0)
                {
                    hv_PointRow = hv_Row_Measure.TupleSelect(0);
                    hv_PointCol = hv_Column_Measure.TupleSelect(0);
                }
                HOperatorSet.SetColor(windowHandle, "yellow");
                HObject circle;
                HOperatorSet.GenCircle(out circle, hv_PointRow, hv_PointCol, 5);
                rsPoint = new Point((double)hv_PointRow, (double)hv_PointCol);
            }
            catch (Exception)
            {
                MessageBox.Show("未能检测到点", "提示", MessageBoxButton.OK);
                
            }
            ho_ImageCopy.Dispose();
            
            return rsPoint;
        }
        public static   Circle Get_circle_fromROI(HObject ho_Image, HObject ho_ROI, HTuple windowHandle,HTuple hv_MinRadius, HTuple hv_MaxRadius, HTuple hv_Threshold1, HTuple hv_Threshold2)
        {
            //HOperatorSet.DispObj(ho_ROI,hv_ExpDefaultWinHandle);
            HTuple area, row, column;
            
            Circle rsCircle = null;
            HOperatorSet.AreaCenter(ho_ROI, out area,out  row,out column);
            HObject[] OTemp = new HObject[20];
            HObject ho_Contours;
            HOperatorSet.GenEmptyObj(out ho_Contours);
            HTuple hv_Number = null, hv_n = null, hv_i = null;
            HTuple hv_Row = new HTuple(), hv_Column = new HTuple();
            HTuple hv_Radius = new HTuple(), hv_StartPhi = new HTuple();
            HTuple hv_EndPhi = new HTuple(), hv_PointOrder = new HTuple();
            HTuple hv_Score = new HTuple();

            HObject ho_ImageReduced, ho_Regions, ho_RegionBorder;
            HObject ho_RegionDilation, ho_Edges, ho_ObjectSelected = null;
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_Contours);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            HOperatorSet.GenEmptyObj(out ho_Regions);
            HOperatorSet.GenEmptyObj(out ho_RegionBorder);
            HOperatorSet.GenEmptyObj(out ho_RegionDilation);
            HOperatorSet.GenEmptyObj(out ho_Edges);
            HOperatorSet.GenEmptyObj(out ho_ObjectSelected);
            //* 模拟画出感兴趣区域并拟合轮廓，提取圆形的例子
            //* 首先是模拟画出了三个圆ROI，并读取对应Regio
            //*然后初始化轮廓数组，用于存储ROI拟合成功的轮廓
            //*设置阈值分割的大小界限，此处暂设为[40,255]
            //*Threshold1 := 40
            //*Threshold2 := 255
            //* 34 38 18 22
            //*对各个ROI区域进行具体的拟合和提取

            //*暂不使用segment_contours_xld进行边缘类型区分
            ho_ImageReduced.Dispose();
           // HOperatorSet.DispObj(ho_Image, windowHandle);
            
            HOperatorSet.ReduceDomain(ho_Image, ho_ROI, out ho_ImageReduced);
   
            //*阈值分割
            HOperatorSet.SetDraw(windowHandle, "fill");
            //* MinRadius 70 MaxRadius 73
            ho_Regions.Dispose();
            HOperatorSet.Threshold(ho_ImageReduced, out ho_Regions, hv_Threshold1, hv_Threshold2);
            //取Region边界
            ho_RegionBorder.Dispose();
            HOperatorSet.Boundary(ho_Regions, out ho_RegionBorder, "inner");
            //*膨胀
            ho_RegionDilation.Dispose();
            HOperatorSet.DilationCircle(ho_RegionBorder, out ho_RegionDilation, 2.5);
            //在弧形区域进行边缘检测
            ho_Edges.Dispose();
            HOperatorSet.EdgesSubPix(ho_ImageReduced, out ho_Edges, "canny", 1, 20, 40);
            //分割边缘：线和圆
            //对检测的边缘进行分割，识别线或者圆'lines_circles'，
            //segment_contours_xld (Edges, ContoursSplit, 'lines_circles', 5, 4, 2)
            //统计识别出圆或线的数量
            //count_obj (ContoursSplit, Number)
            HOperatorSet.CountObj(ho_Edges, out hv_Number);
            ho_Contours.Dispose();
            HOperatorSet.GenEmptyObj(out ho_Contours);

            hv_n = 0;
            HTuple end_val = hv_Number;
            HTuple step_val = 1;
            for (hv_i = 1; hv_i.Continue(end_val, step_val); hv_i = hv_i.TupleAdd(step_val))
            {
                ho_ObjectSelected.Dispose();
                HOperatorSet.SelectObj(ho_Edges, out ho_ObjectSelected, hv_i);
                //逼近结果生成一个圆轮廓
                try
                {
                    HOperatorSet.FitCircleContourXld(ho_ObjectSelected, "geohuber", -1, 2, 0,
                    3, 2, out hv_Row, out hv_Column, out hv_Radius, out hv_StartPhi, out hv_EndPhi,
                    out hv_PointOrder);
                    Get_fitscore_circle(ho_ObjectSelected, hv_Row, hv_Column, hv_Radius, out hv_Score);
                    //*Score界限设置为小于等于1
                    //这里会生成大量的拟合圆，通过添加条件，选取自己需要的圆，这里条件为半径，

                    if ((int)((new HTuple((new HTuple(hv_Score.TupleLessEqual(1))).TupleAnd(new HTuple(hv_Radius.TupleLessEqual(
                        hv_MaxRadius))))).TupleAnd(new HTuple(hv_Radius.TupleGreaterEqual(hv_MinRadius)))) != 0)
                    {
                        //生成轮廓
                        ho_Contours.Dispose();
                        HOperatorSet.GenCircleContourXld(out ho_Contours, hv_Row, hv_Column, hv_Radius, 0, (new HTuple(360)).TupleRad(), "positive", 1.0);
                        //记录圆的圆心坐标和半径信息 

                        break;
                    }
                }
                catch (Exception)
                {
                    MessageBox.Show("未能检测到圆", "提示", MessageBoxButton.OK);
                }
                
                
            }
           
            ho_ImageReduced.Dispose();
            ho_Regions.Dispose();
            ho_RegionBorder.Dispose();
            ho_RegionDilation.Dispose();
            ho_Edges.Dispose();
            ho_ObjectSelected.Dispose();

            if (hv_Row == null || hv_Column == null || ho_Contours == null || hv_Radius == null) return null;
            Point centrePoint = new Point((double)hv_Row, (double)hv_Column);
            rsCircle = new Circle(centrePoint, (double)hv_Radius, ho_Contours);
          //  HObject region;
          //  HOperatorSet.GenRegionContourXld(ho_Contours, out region, new HTuple("margin"));
          //  HOperatorSet.SetLineWidth(windowHandle, 2);
           // HOperatorSet.SetColor(windowHandle, "yellow");
            //HOperatorSet.DispObj(region, windowHandle);
            return  rsCircle;
        }

        public static   Line Get_line_fromROI(HObject ho_Image, HObject ho_ROI,HTuple windowHandle, HTuple hv_Threshold1, HTuple hv_Threshold2)
        {

            // Local iconic variables 
            Line rsLine = null;
            //HTuple area, row, column;
            //HOperatorSet.AreaCenter(ho_ROI, out area, out row, out column);
            
            HObject ho_ImageReduced, ho_Regions, ho_RegionBorder;
            HObject ho_Edges, ho_ContoursSplit, ho_Contours, ho_ObjectSelected = null;
            HObject ho_Line = null;
            // Local control variables 
            HObject region;
            HTuple hv_Number = null, hv_ROW = null, hv_COL = null;
            HTuple hv_Rad = null, hv_n = null, hv_i = null, hv_Attrib = new HTuple();
            HTuple hv_RowBegin = new HTuple(), hv_ColBegin = new HTuple();
            HTuple hv_RowEnd = new HTuple(), hv_ColEnd = new HTuple();
            HTuple hv_Nr = new HTuple(), hv_Nc = new HTuple(), hv_Dist = new HTuple();
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_Line);
            HOperatorSet.GenEmptyObj(out ho_ImageReduced);
            HOperatorSet.GenEmptyObj(out ho_Regions);
            HOperatorSet.GenEmptyObj(out ho_RegionBorder);
            HOperatorSet.GenEmptyObj(out ho_Edges);
            HOperatorSet.GenEmptyObj(out ho_ContoursSplit);
            HOperatorSet.GenEmptyObj(out ho_Contours);
            HOperatorSet.GenEmptyObj(out ho_ObjectSelected);
            //*暂不使用segment_contours_xld进行边缘类型区分

            
            HOperatorSet.ReduceDomain(ho_Image, ho_ROI, out ho_ImageReduced);
            //*阈值分割
            HOperatorSet.SetDraw(windowHandle, "fill");
            //* MinRadius 70 MaxRadius 73
            ho_Regions.Dispose();
            HOperatorSet.Threshold(ho_ImageReduced, out ho_Regions, hv_Threshold1, hv_Threshold2);
            //取Region边界
            ho_RegionBorder.Dispose();
            HOperatorSet.Boundary(ho_Regions, out ho_RegionBorder, "inner");

            //在弧形区域进行边缘检测
            ho_Edges.Dispose();
            HOperatorSet.EdgesSubPix(ho_ImageReduced, out ho_Edges, "canny", 1, 20, 40);
            //分割边缘：线和圆
            //对检测的边缘进行分割，识别线或者圆'lines_circles'，
            ho_ContoursSplit.Dispose();
            HOperatorSet.SegmentContoursXld(ho_Edges, out ho_ContoursSplit, "lines_circles",
                5, 4, 2);
            //统计识别出圆或线的数量
            HOperatorSet.CountObj(ho_ContoursSplit, out hv_Number);
            HOperatorSet.CountObj(ho_Edges, out hv_Number);
            ho_Contours.Dispose();
            HOperatorSet.GenEmptyObj(out ho_Contours);
            //dev_close_window ()
            //dev_open_window (0, 0, 512, 512, 'black', WindowHandle)
            //s (GrayImage)
            //dev_set_draw ('margin')
            //dev_set_color ('red')
            //dev_update_window ('off')
            //储存拟合圆的圆心坐标和半径
            hv_ROW = new HTuple();
            hv_COL = new HTuple();
            hv_Rad = new HTuple();
            hv_n = 0;
            HTuple end_val = hv_Number;
            HTuple step_val = 1;
            for (hv_i = 1; hv_i.Continue(end_val, step_val); hv_i = hv_i.TupleAdd(step_val))
            {
                //选择轮廓并根据特性：* Attrib = -1 线段 0 椭圆 1圆
                ho_ObjectSelected.Dispose();
                HOperatorSet.SelectObj(ho_ContoursSplit, out ho_ObjectSelected, hv_i);
                HOperatorSet.GetContourGlobalAttribXld(ho_ObjectSelected, "cont_approx", out hv_Attrib);
                if ((int)(new HTuple(hv_Attrib.TupleEqual(-1))) != 0)
                {
                    try
                    {
                        HOperatorSet.FitLineContourXld(ho_ObjectSelected, "gauss", -1, 2, 3, 3, out hv_RowBegin,
                         out hv_ColBegin, out hv_RowEnd, out hv_ColEnd, out hv_Nr, out hv_Nc, out hv_Dist);
                        ho_Line.Dispose();
                        rsLine = new Line(new Point((double)hv_RowBegin, (double)hv_ColBegin), new Point((double)hv_RowEnd, (double)hv_ColEnd));
                      //  HOperatorSet.GenContourPolygonXld(out ho_Line, hv_RowBegin.TupleConcat(hv_RowEnd), hv_ColBegin.TupleConcat(hv_ColEnd));
                       // HOperatorSet.GenRegionContourXld(ho_Line, out region, new HTuple("margin"));
                       // HOperatorSet.SetColor(windowHandle, "yellow");
                       // HOperatorSet.SetLineWidth(windowHandle, 2);
                       // HOperatorSet.DispObj(region, windowHandle);
                    }
                    catch (Exception)
                    {
                        MessageBox.Show("未能检测到线", "警告", MessageBoxButton.OK);
                       
                    }
                   
                 
                }
                //*     endif
            }
            ho_ImageReduced.Dispose();
            ho_Regions.Dispose();
            ho_RegionBorder.Dispose();
            ho_Edges.Dispose();
            ho_ContoursSplit.Dispose();
            ho_Contours.Dispose();
            ho_ObjectSelected.Dispose();

            return rsLine;
        }


        public static   void Get_fitscore_circle(HObject ho_Contours, HTuple hv_Row, HTuple hv_Col,HTuple hv_Radius, out HTuple hv_Score)
        {
            HObject ho_Points = null;

            // Local control variables 

            HTuple hv_Dist = null, hv_Sum = null, hv_e = null;
            HTuple hv_Number = null, hv_i = null, hv_Row1 = new HTuple();
            HTuple hv_Col1 = new HTuple(), hv_Distance = new HTuple();
            HTuple hv_Aver = null;
            // Initialize local and output iconic variables 
            HOperatorSet.GenEmptyObj(out ho_Points);
            hv_Dist = new HTuple();
            hv_Sum = 0;
            hv_e = 0;
            HOperatorSet.CountObj(ho_Contours, out hv_Number);
            //
            HTuple end_val5 = hv_Number;
            HTuple step_val5 = 1;
            for (hv_i = 1; hv_i.Continue(end_val5, step_val5); hv_i = hv_i.TupleAdd(step_val5))
            {
                ho_Points.Dispose();
                HOperatorSet.SelectObj(ho_Contours, out ho_Points, hv_i);
                HOperatorSet.GetContourXld(ho_Points, out hv_Row1, out hv_Col1);
            }
            //
            for (hv_i = 0; (int)hv_i <= (int)(new HTuple(hv_Row1.TupleLength()) - 1); hv_i = (int)hv_i + 1)
            {
                HOperatorSet.DistancePp(hv_Row, hv_Col, hv_Row1.TupleSelect(hv_i), hv_Col1.TupleSelect(
                    hv_i), out hv_Distance);
                if (hv_Dist == null)
                    hv_Dist = new HTuple();
                hv_Dist[hv_i] = hv_Distance;
                hv_Sum = hv_Sum + hv_Distance;
            }
            //
            hv_Aver = hv_Sum / (new HTuple(hv_Row1.TupleLength()));
            for (hv_i = 0; (int)hv_i <= (int)((new HTuple(hv_Row1.TupleLength())) - 1); hv_i = (int)hv_i + 1)
            {
                hv_e = hv_e + (((hv_Dist.TupleSelect(hv_i)) - hv_Aver) * ((hv_Dist.TupleSelect(hv_i)) - hv_Aver));
            }
            hv_e = hv_e / ((new HTuple(hv_Row1.TupleLength())) - 1);
            hv_Score = hv_e.TupleSqrt();
            //
            //

            ho_Points.Dispose();
            ho_Points.Dispose();




            return;
        }



        public static  Point Detect_LL_Cross(Line line1, Line line2)
        {
            HTuple row, column;
            GeoMethod.LL_Cross(line1.LineContours, line2.LineContours, out row, out column);
            Point point = new Point((double)row, (double)column);
            return point;
        }

        public static  Point Detect_LC_Cross(Line line, Circle circle)
        {
            HTuple row, column;
            GeoMethod.LC_Cross(line.LineContours, circle.CircleContours, out row, out column);
            Point point = new Point((double)row, (double)column);
            return point;
        }

        public static  Point Detect_CC_Cross(Circle circle1, Circle circle2)
        {
            HTuple row, column;
            GeoMethod.CC_Cross(circle1.CircleContours, circle2.CircleContours, out row, out column);
            Point point = new Point((double)row, (double)column);
            return point;
        }

        public static  Point Detect_C_Center(Circle circle)
        {
            HTuple row, column;
            GeoMethod.C_Center(circle.CircleContours, out row, out column);
            Point point = new Point((double)row, (double)column);
            return point;
        }

        public static  Point Detect_P_Mid(Point point1, Point point2)
        {
            HTuple row, column;
            GeoMethod.P_Mid(point1.Row, point1.Column, point2.Row, point2.Column, out row, out column);
            Point point = new Point((double)row, (double)column);
            return point;
        }
        public static  Line Detect_LL_Mid(Line line1, Line line2)
        {
            HObject midLine;
            HTuple rowBegin, colBegin, rowEnd, colEnd;
            GeoMethod.LL_Mid(line1.LineContours, line2.LineContours, out midLine, out rowBegin, out colBegin, out rowEnd, out colEnd);
            Line line = new Line(rowBegin, colBegin, rowEnd, colEnd);
            return line;
        }

        public static  Line Detect_PL_Mid(Point point, Line line)
        {
            HObject midLine;
            HTuple rowBegin, colBegin, rowEnd, colEnd;
            GeoMethod.PL_Mid(line.LineContours, out midLine, point.Row, point.Column, out rowBegin, out colBegin, out rowEnd, out colEnd);
            Line result = new Line(rowBegin, colBegin, rowEnd, colEnd);
            return result;
        }

        public static  Line Detect_PL_VERTICAL(Point point, Line line)
        {
            HObject midLine;
            HTuple rowBegin, colBegin, rowEnd, colEnd;
            GeoMethod.PL_VERTICAL(line.LineContours, out midLine, point.Row, point.Column, out rowBegin, out colBegin, out rowEnd, out colEnd);
            Line result = new Line(rowBegin, colBegin, rowEnd, colEnd);
            return result;
        }

        public static  Line Detect_PL_Parallel(Point point, Line line)
        {
            HObject parallelLine;
            HTuple rowBegin, colBegin, rowEnd, colEnd;
            GeoMethod.PL_Parallel(line.LineContours, point.Row, point.Column, out parallelLine, out rowBegin, out colBegin, out rowEnd, out colEnd);
            Line result = new Line(rowBegin, colBegin, rowEnd, colEnd);
            return result;
        }

        public static  Line Detect_PP_Mid(Point point1, Point point2)
        {
            HObject midLine;
            HTuple rowBegin, colBegin, rowEnd, colEnd;
            GeoMethod.PP_Mid(out midLine, point1.Row, point1.Column, point2.Row, point2.Column, out rowBegin, out colBegin, out rowEnd, out colEnd);
            Line result = new Line(rowBegin, colBegin, rowEnd, colEnd);
            return result;
        }

        public static  Line Detect_P_FitLine(List<Point> points)
        {
            HObject fitLine;
            HTuple rows = null, cols = null;
            HTuple rowBegin, colBegin, rowEnd, colEnd;
            foreach (var point in points)
            {
                if (rows == null)
                {
                    rows = new HTuple(point.Row);
                    cols = new HTuple(point.Column);
                }
                else
                {
                    rows.TupleConcat(new HTuple(point.Row));
                    cols.TupleConcat(new HTuple(point.Column));
                }
            }
            GeoMethod.P_FitLine(out fitLine, rows, cols, out rowBegin, out colBegin, out rowEnd, out colEnd);
            Line result = new Line(rowBegin, colBegin, rowEnd, colEnd);
            return result;
        }

        public static  Line Detect_LL_Concate(List<Line> lines)
        {
            HObject concateLine;
            HObject lineContours = null;
            HTuple rowBegin, colBegin, rowEnd, colEnd;
            foreach (var line in lines)
            {
                if (lineContours == null)
                {
                    lineContours = new HObject(line.LineContours);
                }
                else
                {
                    lineContours.ConcatObj(line.LineContours);
                }
            }
            GeoMethod.LL_Concate(lineContours, out concateLine, out rowBegin, out colBegin, out rowEnd, out colEnd);
            Line result = new Line(rowBegin, colBegin, rowEnd, colEnd);
            return result;
        }

        public static  Circle Detect_C_Fit(List<Point> points)
        {
            HObject fitCircle;
            HTuple rows = null, cols = null;
            HTuple row, column, radius;
            foreach (var point in points)
            {
                if (rows == null)
                {
                    rows = new HTuple(point.Row);
                    cols = new HTuple(point.Column);
                }
                else
                {
                    rows.TupleConcat(new HTuple(point.Row));
                    cols.TupleConcat(new HTuple(point.Column));
                }
            }
            GeoMethod.C_Fit(out fitCircle, rows, cols, out row, out column, out radius);
            Point centrePoint = new Point(rows, column);
            Circle result = new Circle(centrePoint, radius, fitCircle);
            return result;
        }

        public static  Circle Detect_CC_Mid(Circle c1, Circle c2)
        {
            HObject fitCircle;
            HTuple centreRow, centreColumn, radius;
            GeoMethod.CC_Mid(c1.CircleContours, c2.CircleContours, out fitCircle, out centreRow, out centreColumn, out radius);
            Point centrePoint = new Point(centreRow, centreColumn);
            Circle result = new Circle(centrePoint, radius, fitCircle);
            return result;
        }

        public static  Circle Detect_C_SUP(Point point, double radius)
        {
            HObject supCircle;
            GeoMethod.C_SUP(out supCircle, point.Row, point.Column, radius);
            Circle result = new Circle(point, radius, supCircle);
            return result;
        }

        public static  Circle Detect_LL_InnerC(List<Line> lines)
        {
            HObject innerCircle;
            HObject lineContours = null;
            HTuple centreRow, centreColumn, radius;
            foreach (var line in lines)
            {
                if (lineContours == null)
                {
                    lineContours = new HObject(line.LineContours);
                }
                else
                {
                    lineContours.ConcatObj(line.LineContours);
                }
            }
            GeoMethod.LL_InnerC(lineContours, out innerCircle, out centreRow, out centreColumn, out radius);
            Point centrePoint = new Point(centreRow, centreColumn);
            Circle result = new Circle(centrePoint, radius, innerCircle);
            return result;
        }

        public static  Circle Detect_Arc_Concat(List<Line> lines)
        {
            HObject concateCircle;
            HObject lineContours = null;
            HTuple centreRow, centreColumn, radius;
            foreach (var line in lines)
            {
                if (lineContours == null)
                {
                    lineContours = new HObject(line.LineContours);
                }
                else
                {
                    lineContours.ConcatObj(line.LineContours);
                }
            }
            GeoMethod.Arc_Concat(lineContours, out concateCircle, out centreRow, out centreColumn, out radius);
            Point centrePoint = new Point(centreRow, centreColumn);
            Circle result = new Circle(centrePoint, radius, concateCircle);
            return result;
        }


        public static  double Detect_PP_DIST(Point point1, Point point2)
        {
            HTuple distance;
            HOperatorSet.DistancePp(point1.Row, point1.Column, point2.Row, point2.Column, out distance);
            return (double)distance;
        }//点点距离
        public static  HTuple Detect_PL_DIST(Point point, Line line)
        {
            HTuple distance;
            HTuple rowBegin, colBegin, rowEnd, colEnd, nr, nc, dist;
            HOperatorSet.FitLineContourXld(line.LineContours, "turkey", -1, 0, 5, 2.0, out rowBegin, out colBegin, out rowEnd, out colEnd, out nr, out nc, out dist);
            HOperatorSet.DistancePl(point.Row, point.Column, rowBegin, colBegin, rowEnd, colEnd, out distance);
            return (double)distance;
        }//点线距离
        public static  double Detect_LL_Dist(Line line1, Line line2)
        {
            HTuple distance;
            GeoMethod.LL_Dist(line1.LineContours, line2.LineContours, out distance);
            return (double)distance;
        }//线线距离
        public static  double[] Detect_PC_DIST(Point point, Circle circle)
        {
            HTuple minDist, maxDist;
            HOperatorSet.DistancePc(circle.CircleContours, point.Row, point.Column, out minDist, out maxDist);
            double[] rs = { minDist, maxDist };
            return rs;
        }//点圆距离
        public static  double[] Detect_LC_DIST(Line line, Circle circle)
        {
            HTuple minDist, maxDist;
            HTuple rowBegin, colBegin, rowEnd, colEnd, nr, nc, dist;
            HOperatorSet.FitLineContourXld(line.LineContours, "turkey", -1, 0, 5, 2.0, out rowBegin, out colBegin, out rowEnd, out colEnd, out nr, out nc, out dist);
            HOperatorSet.DistanceLc(circle.CircleContours, rowBegin, colBegin, rowEnd, colEnd, out minDist, out maxDist);
            double[] rs = { minDist, maxDist };
            return rs;
        }//线圆距离
        public static  double[] Detect_CC_DIST(Circle circle1, Circle circle2)
        {
            HTuple minDist, maxDist;
            HOperatorSet.DistanceCc(circle1.CircleContours, circle2.CircleContours, "point_to_point", out minDist, out maxDist);
            double[] rs = { minDist, maxDist };
            return rs;
        }//圆圆距离
        public static  double Detect_C_RADIUS(Circle circle)
        {
            HTuple row, column, radius, startPhi, endPhi, order;
            HOperatorSet.FitCircleContourXld(circle.CircleContours, "algebraic", -1, 0.0, 0, 3, 2.0, out row, out column, out radius, out startPhi, out endPhi, out order);
            return (double)radius;

        }//圆径
        public static  double Detect_ARC_ANGLE(Line arc)
        {
            HTuple row, column, radius, startPhi, endPhi, order;
            HOperatorSet.FitCircleContourXld(arc.LineContours, "algebraic", -1, 0.0, 0, 3, 2.0, out row, out column, out radius, out startPhi, out endPhi, out order);
            return (double)(endPhi - startPhi);
        }//弧度
        public static  double Detect_LL_ANGLE(Line line1, Line line2)
        {
            HTuple angle;
            HOperatorSet.AngleLl(line1.StartPoint.Row, line1.StartPoint.Column, line1.EndPoint.Row, line1.EndPoint.Column, line2.StartPoint.Row, line2.StartPoint.Column, line2.EndPoint.Row, line2.EndPoint.Column, out angle);
            return (double)angle;
        }//线夹角度
    }
}
